﻿/*
 * Created by SharpDevelop.
 * User: Guy Fomi
 * Date: 2/6/2011
 * Time: 2:14 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Collections;
using System.Collections.Generic;
using HtmlAgilityPack;
using System.Web.Script.Serialization;
using FileSystemDatabase;
using TomatoSynchronizer.Entities;
using Newtonsoft.Json;
using System.IO;
using Newtonsoft.Json.Linq;
using antiufo.HttpPost;
using System.Collections.Specialized;
using System.Net;

namespace TomatoSynchronizer.Store
{
	/// <summary>
	/// Description of UnitClassStore.
	/// </summary>
	public class UnitClassStore : IStore<UnitClass>
	{
		private Site _site;
		public Site site {
			get { return _site; }
			set { _site = value; }
		}
		
		private HtmlWeb _client;
		
		private JsonDatabase db;
		
		public UnitClassStore(Site site,HtmlWeb client)
		{
			db = new JsonDatabase("sites/" + site.Name + "/UnitClasses");
			_site = site;
			_client = client;
		}
		
		public void PersistItems(List<UnitClass> items)
		{
			db.Write<List<UnitClass>>(items,_site.Name);
		}
		
		public void Truncate()
		{
			UnitClass[] _uclasses = LoadItems();
			
			foreach(UnitClass uclass in _uclasses)
			{
				if(uclass.is_default == 1)
				{
					
				}
				else
				{
					bool deleted = DeleteItem(uclass.unit_class_id);
					if(!deleted)
					{
						throw new Exception("Could not delete the UnitClass " + uclass.unit_class_id + " in site " + _site.Name);
					}
					
					db.Delete<UnitClass>(uclass.unit_class_id);
				}
			}
		}
		
		public void PersistItem(UnitClass item)
		{
			db.Write<UnitClass>(item,item.unit_class_id);
		}
		
		public bool MoveItem(string itemId, string folderId)
		{
			throw new NotImplementedException();
		}
		
		public bool DeleteItem(string itemId)
		{
			string url = _site.Url + "/admin/json.php?action=delete_unit_class&module=unit_classes&unit_class_id=" + itemId;
			HtmlDocument doc = _client.Load(url);

			HtmlNode node = doc.DocumentNode.SelectSingleNode("/");
			JavaScriptSerializer serialiser = new JavaScriptSerializer();
			IDictionary json = serialiser.Deserialize<IDictionary>(node.InnerText);
			foreach (string key in json.Keys) {
				if (key == "success") {
					var response = bool.Parse(json[key].ToString());
					if (response) {
						db.Delete<UnitClass>(itemId);
					}

					return response;
				}
			}

			throw new Exception("Could not delete the UnitClass " + itemId + " in site " + _site.Name);
		}
		
		public UnitClass[] LoadItems()
		{
			UnitClass[] items = db.Read<UnitClass>();
			foreach(UnitClass item in items)
			{
				item.Store = this;
			}
			return items;
		}
		
		public UnitClass LoadItem(string itemId)
		{
			UnitClass item = db.Read<UnitClass>(itemId);
			if (item != null) {
				item.Store = this;
				return item;
			}

			return null;
		}
		
		public bool Contains(UnitClass item)
		{
			throw new NotImplementedException();
		}
		
		private List<UnitClass> uclasses;
		public List<UnitClass> GetItems()
		{
			db.Truncate();
			uclasses = new List<UnitClass>();
			
			string url = _site.Url + "/admin/json.php?action=list_unit_classes&module=unit_classes";
			HtmlDocument doc = _client.Load(url);
			HtmlNode node = doc.DocumentNode.SelectSingleNode("/");
			
			JavaScriptSerializer serialiser = new JavaScriptSerializer();
			Dictionary<string,object> json = serialiser.Deserialize<Dictionary<string,object>>(node.InnerText);
			foreach (string key in json.Keys) {
				if (key == "records") {
					ArrayList recs = (ArrayList)json[key];
					for (int i = 0; i < recs.Count; i++) {
						Dictionary<string, object> record = (Dictionary<string, object>)recs[i];
						UnitClass uclass = GetItem(record["unit_class_id"].ToString());
						uclass.unit_class_id = record["unit_class_id"].ToString();
						uclass.language_id = record["languange_id"].ToString();
						uclasses.Add(uclass);
						PersistItem(uclass);
					}
				}
			}
			
			PersistItems(uclasses);
			
			return uclasses;
		}

		public List<UnitClass> DownloadItems()
		{
			uclasses = new List<UnitClass>();
			
			string url = _site.Url + "/admin/json.php?action=list_unit_classes&module=unit_classes";
			HtmlDocument doc = _client.Load(url);
			HtmlNode node = doc.DocumentNode.SelectSingleNode("/");
			
			JavaScriptSerializer serialiser = new JavaScriptSerializer();
			Dictionary<string,object> json = serialiser.Deserialize<Dictionary<string,object>>(node.InnerText);
			foreach (string key in json.Keys) {
				if (key == "records") {
					ArrayList recs = (ArrayList)json[key];
					for (int i = 0; i < recs.Count; i++) {
						Dictionary<string, object> record = (Dictionary<string, object>)recs[i];
						UnitClass uclass = GetItem(record["unit_class_id"].ToString());
						uclass.unit_class_id = record["unit_class_id"].ToString();
						uclass.language_id = record["languange_id"].ToString();
						uclasses.Add(uclass);
					}
				}
			}
			
			return uclasses;
		}
		
		public UnitClass GetItem(string itemId)
		{
			string url = _site.Url + "/admin/json.php?action=load_unit_class&module=unit_classes&unit_class_id=" + itemId;

			HtmlDocument doc = _client.Load(url);
			HtmlNode node = doc.DocumentNode.SelectSingleNode("/");

			try {
				JObject json = (JObject)JsonConvert.DeserializeObject(node.InnerText);
				foreach (JProperty property in json.Properties()) {
					if (property.Name == "data") {
						var val = property.Value.ToString();
						UnitClass uclass = new UnitClass(val);
						uclass.unit_class_id = itemId;
						uclass.language_id = Default_language_id;
						uclass.Store = this;
						return uclass;
					}
				}

				throw new Exception("Could not load the UnitClass " + itemId);
			} catch (JsonReaderException ex) {
				throw ex;
			}
		}
		
		public bool UpdateItem(UnitClass item)
		{
			var post = new antiufo.HttpPost.HttpPostRequest(_site.Url + "/admin/json.php");

			post.AddField("action", "save_unit_class");
			post.AddField("module", "unit_classes");
			post.AddField("unit_class_id",item.unit_class_id);
			if(item.is_default == 1)
			{
				post.AddField("default", "on");
			}
			
			foreach(string key in item.unit_class_titles.Keys)
			{
				post.AddField(key,item.unit_class_titles[key]);
			}

			var resp = post.PostData();

			Stream s = resp.GetResponseStream();
			StreamReader sr = new StreamReader(s);

			var response = sr.ReadToEnd();

			JavaScriptSerializer serialiser = new JavaScriptSerializer();
			IDictionary json = serialiser.Deserialize<IDictionary>(response);
			if (json != null) {
				foreach (string key in json.Keys) {
					if (key == "success") {
						return bool.Parse(json[key].ToString());
					}
				}
			}

			throw new Exception("Could not update the UnitClass " + item.unit_class_id + " in site " + _site.Name);
		}				
		
		public string Default_language_id {
			get
			{
				var languages = site.GetLanguageStore().LoadItems();
				
				foreach(Language language in languages)
				{
					if(language.is_default)
					{
						return language.languages_id;
					}
				}
				
				throw new Exception("Could not get the default language ID in store " + site.Name);
			}
		}
		
		public string InsertItem(UnitClass item)
		{
			var post = new antiufo.HttpPost.HttpPostRequest(_site.Url + "/admin/json.php");

			post.AddField("action", "save_unit_class");
			post.AddField("module", "unit_classes");
			if(item.is_default == 1)
			{
				post.AddField("default", "on");
			}
			
			foreach(string key in item.unit_class_titles.Keys)
			{
				post.AddField(key,item.unit_class_titles[key]);
			}
			
			//we set the language_id of the dest UnitClass
			//we set the new keys and names based on the dest language_ids
			
			string oldLangId = item.language_id;
			item.language_id = Default_language_id;

			var resp = post.PostData();

			Stream s = resp.GetResponseStream();
			StreamReader sr = new StreamReader(s);

			var response = sr.ReadToEnd();

			item.language_id = oldLangId;
			
			JavaScriptSerializer serialiser = new JavaScriptSerializer();
			IDictionary json = serialiser.Deserialize<IDictionary>(response);
			if (json != null) {
				foreach (string key in json.Keys) {
					if (key == "success") {
						if (bool.Parse(json[key].ToString())) {
							
							var uclasses = DownloadItems();
							
							foreach(UnitClass uclass in uclasses)
							{
								var rclass = LoadItem(uclass.unit_class_id);
								
								if(rclass == null && uclass.is_default == item.is_default)
								{
									PersistItem(uclass);
									return uclass.unit_class_id;
								}
							}
						}
					}
				}
			}

			throw new Exception("Could not insert the UnitClass " + item.unit_class_id + " in site " + _site.Name);
		}
	}
}
